﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;

using Microsoft.TeamFoundation.WorkItemTracking.Client;


namespace Qetza.TeamFoundation.WorkItemQuery.Admin
{
    /// <summary>
    /// Command to export a work item query.
    /// </summary>
    public class CommandExportWiq : ICommand
    {
        #region ICommand Members

        /// <inheritdoc />
        public string Name
        {
            get { return "export"; }
        }

        /// <inheritdoc />
        public string HelpText
        {
            get { return ResourceStrings.ExportWiqHelpText; }
        }

        /// <inheritdoc />
        public IEnumerable<ParameterInfo> AllowedParameters
        {
            get
            {
                return new[] {
                    new ParameterInfo() { 
                        Name = CoreArgumentNames.Collection, 
                        ArgumentName = ResourceStrings.ProjectCollectionArgument, 
                        IsRequired = true, 
                        HelpText = ResourceStrings.ProjectCollectionHelpText
                        },
                    new ParameterInfo() { 
                        Name = CoreArgumentNames.Project, 
                        ArgumentName = ResourceStrings.ProjectArgument, 
                        IsRequired = true, 
                        HelpText = ResourceStrings.ProjectHelpText
                        }, 
                    new ParameterInfo() {
                        Name = CoreArgumentNames.QueryPath,
                        ArgumentName = ResourceStrings.QueryPathArgument,
                        IsRequired = true,
                        HelpText = ResourceStrings.Export_QueryPathHelpText
                        },
                    new ParameterInfo() {
                        Name = CoreArgumentNames.File,
                        ArgumentName = ResourceStrings.FileArgument, 
                        IncompatibleArguments = new [] { CoreArgumentNames.Directory },
                        HelpText = ResourceStrings.Export_FileHelpText
                        },
                    new ParameterInfo() {
                        Name = CoreArgumentNames.Directory,
                        ArgumentName = ResourceStrings.DirectoryArgument,
                        HelpText = ResourceStrings.Export_DirectoryHelpText
                        },
                    new ParameterInfo() {
                        Name = CoreArgumentNames.NoPath,
                        ArgumentName = ResourceStrings.NoPathArgument,
                        HelpText = ResourceStrings.Export_NoPathHelpText,
                        IsFlag = true
                        },
                    new ParameterInfo() {
                        Name = CoreArgumentNames.Encoding,
                        ArgumentName = ResourceStrings.EncodingArgument,
                        HelpText = ResourceStrings.EncodingHelpText
                        }
                    };
            }
        }

        /// <inheritdoc />
        public void Execute(IDictionary<string, string> parameters)
        {
            // get query
            var queryHierarchy = TfsUtility
                .GetWorkItemStore(parameters[CoreArgumentNames.Collection], parameters.ContainsKey(CoreArgumentNames.NoPrompt))
                .Projects[parameters[CoreArgumentNames.Project]]
                .QueryHierarchy;

            if (parameters[CoreArgumentNames.QueryPath][0] == '@')
            {
                // export query from file
                using (var file = new System.IO.StreamReader(parameters[CoreArgumentNames.QueryPath].Substring(1)))
                {
                    var line = default(string);
                    while ((line = file.ReadLine()) != null)
                    {
                        try
                        {
                            if (!string.IsNullOrEmpty(line))
                            {
                                this.ExportQuery(parameters, line, queryHierarchy);
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ResourceStrings.ErrorExportQuery, line, ex.Message);
                        }
                    }
                }
            }
            else
            {
                // export single query
                this.ExportQuery(parameters, parameters[CoreArgumentNames.QueryPath], queryHierarchy);
            }

            if (parameters.ContainsKey(CoreArgumentNames.File) || parameters.ContainsKey(CoreArgumentNames.Directory))
            {
                Console.WriteLine(ResourceStrings.OperationCompleted);
            }
        }

        /// <inheritdoc />
        public void ValidateParameters(IDictionary<string, string> parameters)
        {
            // validate that a directory was specified if query path is a filename (starts with @)
            if (parameters[CoreArgumentNames.QueryPath][0] == '@' && !parameters.ContainsKey(CoreArgumentNames.Directory))
            {
                throw new InvalidParameterException(ResourceStrings.ErrorDirectoryMustBeSpecified);
            }
        }

        #endregion

        #region Private Helpers

        private void ExportQuery(IDictionary<string, string> parameters, string queryPath, QueryHierarchy queryHierarchy)
        {
            // get query
            var query = queryHierarchy.Find(queryPath);
            if (query == null)
            {
                throw new Exception(string.Format(ResourceStrings.ErrorUnknownWorkItemQuery, queryPath));
            }

            if (!(query is QueryDefinition))
            {
                throw new Exception(string.Format(ResourceStrings.ErrorNotAQuery, queryPath));
            }

            // create xml
            var xml = new XDocument(
                new XDeclaration(
                    "1.0",
                    parameters.ContainsKey(CoreArgumentNames.Encoding) ? parameters[CoreArgumentNames.Encoding] : "utf-8",
                    null
                    ),
                new XElement(
                    "WorkItemQuery",
                    new XAttribute("Version", "1"),
                    new XElement("Wiql", ((QueryDefinition)query).QueryText)
                    )
                );

            // write to output
            if (parameters.ContainsKey(CoreArgumentNames.File))
            {
                xml.Save(parameters[CoreArgumentNames.File]);
            }
            else if (parameters.ContainsKey(CoreArgumentNames.Directory))
            {
                // compute path
                var path = parameters[CoreArgumentNames.Directory];
                if (!parameters.ContainsKey(CoreArgumentNames.NoPath))
                {
                    path = Path.Combine(path, Path.GetDirectoryName(queryPath.Replace('/', '\\')));
                }

                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                path = Path.ChangeExtension(
                    Path.Combine(path, Path.GetFileName(queryPath.Replace('/', '\\'))),
                    ".wiq"
                    );

                // save query
                xml.Save(path);
            }
            else
            {
                Console.WriteLine(xml.Declaration);
                Console.WriteLine(xml);
            }
        }

        #endregion
    }
}
